package mysgoog.brown.dragon;

import java.util.Hashtable;
import java.util.LinkedList;

import mysgoog.brown.Brown;

public class Dragon_data {
	/**
	 * The dragon safety can take on one of the values
	 */

	public static final int TACTICALLY_DEAD = 1;
	// a dragon consisting of a single worm found dead by the reading code (very
	// reliable)
	public static final int ALIVE = 2;
	// - found alive by the owl or semeai code
	public static final int STRONGLY_ALIVE = 3;
	// - alive without much question
	public static final int INVINCIBLE = 4;
	// - definitively alive even after many tenukis
	public static final int ALIVE_IN_SEKI = 5;
	// - determined to be seki by the semeai code
	public static final int CRITICAL = 6;
	// - lives or dies depending on who moves first
	public static final int DEAD = 7;
	// - found to be dead by the owl code
	public static final int INESSENTIA = 8;
	// L - the dragon is unimportant (e.g. nakade stones) and dead

	private int color;
	public int id;
	private int origin;
	private int size;
	private double effectSize;
	private int crudeStatus;
	private int status;
	public static int maxId = 0;

	public int[] stones = new int[Brown.maxSize];

	static private double[] w = { 1, 0.5, 0.35, 0.25 };

	static private double wu = 1;
	static private double wt = 0.2;
	static private double we = 1.6;

	public Dragon_data() {
		color = Brown.EMPTY;
		size = 0;
	}

	public int getColor() {
		return color;
	}

	private int getKosuri(int pos) {
		int kosuri = 0;
		int otherColor = Brown.OTHER_COLOR(color);
		int i = Brown.I(pos);
		int j = Brown.J(pos);
		for (int k = 0; k < 4; ++k) {
			int ai = i + Brown.deltai[k];
			int aj = j + Brown.deltaj[k];
			int apos = Brown.POS(ai, aj);
			if (Brown.on_board(ai, aj) && Brown.board[apos] == otherColor) {
				kosuri += 1;
			}
		}

		if (Brown.isEdge(pos))
			kosuri++;

		if (kosuri > 0
				&& (i == 1 || j == 1 || i == Brown.board_size - 2 || j == Brown.board_size - 2))
			kosuri++;

		return kosuri;
	}

	/**
	 * Estimating the Possible Omission Number for Groups in Go by the Number of
	 * n-th Dame
	 * 
	 * @return
	 */
	public double getPON() {
		int stmp;
		double S = 0;

		/**
		 * from position to the dame value
		 */
		Hashtable<Integer, Integer> dames = new Hashtable<Integer, Integer>();

		Hashtable<Integer, Boolean> ks = new Hashtable<Integer, Boolean>();
		LinkedList<Integer> list = new LinkedList<Integer>();
		Hashtable<Integer, Integer> pre = new Hashtable<Integer, Integer>();

		int kosuri;

		for (int i = 0; i < size; i++) {
			stmp = stones[i];

			// color = stmp.getState();

			for (int k = 0; k < 4; ++k) {
				int ai = Brown.I(stmp) + Brown.deltai[k];
				int aj = Brown.J(stmp) + Brown.deltaj[k];
				int apos = Brown.POS(ai, aj);
				if (Brown.on_board(ai, aj) && Brown.board[apos] == Brown.EMPTY) {
					dames.put(apos, 1);
					list.addLast(apos);
				}
			}
		}

		while (!list.isEmpty()) {
			stmp = list.removeFirst();

			kosuri = getKosuri(stmp);

			if (pre.get(stmp) != null) {
				int pretmp = pre.get(stmp);
				if (ks.get(pretmp) != null && ks.get(pretmp) == true)
					kosuri++;
			}

			if (kosuri > 1)
				continue;

			int dis = dames.get(stmp);
			if (Brown.isEdge(stmp)) {
				S += w[dis - 1] * we;
				ks.put(stmp, false);
			} else if (kosuri == 1) {
				S += w[dis - 1] * wt;
				ks.put(stmp, true);
			} else {
				S += w[dis - 1] * wu;
				ks.put(stmp, false);
			}

			if (dis < 4) {
				for (int k = 0; k < 4; ++k) {
					int ai = Brown.I(stmp) + Brown.deltai[k];
					int aj = Brown.J(stmp) + Brown.deltaj[k];
					int apos = Brown.POS(ai, aj);
					if (Brown.on_board(ai, aj)
							&& Brown.board[apos] == Brown.EMPTY) {
						dames.put(apos, dis + 1);
						list.addLast(apos);
						pre.put(stmp, apos);
					}
				}

			}
		}

		return S * 0.33 - 1.96;
	}
}
